﻿using EDXLSharp.EDXLDELib;
using ICNETServices;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Xml.Xsl;

namespace GISUtil.HTML
{
  public class HTMLEngine
  {
    /// <summary>
    /// Log4net logging object
    /// </summary>
    private static readonly log4net.ILog Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

    /// <summary>
    /// Map from xml message types to xsl files that can turn them into HTML reports
    /// </summary>
    private static Dictionary<string, string> xmlTransformers = new Dictionary<string, string>() 
        { 
            { "{http://icnet.mitre.org/mEXL/SitRep/}SitRep", @"\Resources\XSLT\HTML SitRep Legacy.xsl" }, // Minimally tested
            { "{urn:oasis:names:tc:emergency:EDXL:SitRep:1.0}SitRep", @"\Resources\XSLT\HTML SitRep.xsl" }, // Minimally tested
            { "{urn:oasis:names:tc:emergency:EDXL:RM:1.0:msg}OfferUnsolicitedResource", @"\Resources\XSLT\HTML RM.xsl" },  // NOT TESTED
            { "{urn:oasis:names:tc:emergency:EDXL:HAVE:1.0}HospitalStatus", @"\Resources\XSLT\HTML HAVE.xsl" }, // well Tested
            { "{urn:cot:mitre:org}event", @"\Resources\XSLT\HTML CoT.xsl" }, // tested, has issues inserting the human readable type string
            { "{urn:oasis:names:tc:emergency:cap:1.1}alert", @"\Resources\XSLT\HTML CAP 1.1.xsl" },  // NOT TESTED
            { "{urn:oasis:names:tc:emergency:cap:1.2}alert", @"\Resources\XSLT\HTML CAP 1.2.xsl" },  // NOT TESTED
            { "{http://mitre.org/emevent/0.8/cad2cad/}Event", @"\Resources\XSLT\HTML CAD.xsl"}
        };

    public static string GenerateHTMLForContentObject(ContentObject co)
    {
      XElement xe = co.XMLContent.EmbeddedXMLContent.SingleOrDefault();

      if (xe == null)
      {
        Log.Info("No XML found for this content object.");
        return "<html><head><title>No XML Content</title></head><body>No XML content for this content object.</body></html>";
      }

      if(xmlTransformers.ContainsKey(xe.Name.ToString())) {
        Log.InfoFormat("Will transform embeddedXML with ICNET_ROOT{0}", xmlTransformers[xe.Name.ToString()]);
        string html = TransformXML(xe, ICNETSOAConstants.ICNET_ROOT + xmlTransformers[xe.Name.ToString()]);
        Log.Info("Generated HTML: " + html);
        return html;
      } else {
        Log.WarnFormat("No XSLT found for XML name ({0}).", xe.Name.ToString());
        return "<html><head><title>No Template for XML Type</title></head><body>No XML content for this embeddedXML type " + xe.Name.ToString() + ".</body></html>";
      }

    }

    private static string TransformXML(XElement xe, string xsltFile)
    {
      try
      {
        XslTransform xslt = new XslTransform();


        XslCompiledTransform xsltc = new XslCompiledTransform();
        XsltSettings xslt_settings = new XsltSettings();
        xslt_settings.EnableScript = true;
        xslt_settings.EnableDocumentFunction = true;
        

        XmlResolver resolver = new XmlUrlResolver();
       
        //resolver.Credentials = CredentialCache.DefaultCredentials;

        StringBuilder htmlOutput = new StringBuilder();
        XmlWriter htmlWriter = XmlWriter.Create(htmlOutput, new XmlWriterSettings()
        {
          OmitXmlDeclaration = true
        });

        //xslt.Load(xsltFile, xslt_settings, resolver);
        xslt.Load(xsltFile, resolver);
        xslt.Transform(new XPathDocument(xe.CreateReader()), null, htmlWriter);


        //xslt.Transform(new XPathDocument(xe.CreateReader()), htmlWriter);

        htmlWriter.Flush();
        htmlWriter.Close();
        return htmlOutput.ToString();
      }
      catch (XsltCompileException xsltce)
      {
        Log.Error(xsltce);
        return "<html><head><title>XSLT Compile Failed</title></head><body>XSLT compile failed. Check logs for details.</body></html>";
      }
      catch (XsltException xslte)
      {
        Log.Error(xslte);
        return "<html><head><title>XSLT Transfrom Failed</title></head><body>XSLT transform failed. Check logs for details.</body></html>";
      }
      catch (Exception e)
      {
        Log.Error(e);
        return "<html><head><title>XSLT Compile Failed</title></head><body>XSLT compile or transform failed. Check logs for details.</body></html>";
      }
    }
  }

  
}
